/*
  Losu Copyright Notice
  --------------------
    Losu is an open source programming language project under the MIT license
  that can be used for both academic and commercial purposes. There are no
  fees, no royalties, and no GNU-like "copyright" restrictions. Losu qualifies
  as open source software. However, Losu is not public property, and founder
  'chen-chaochen' retains its copyright.

    Losu has been registered with the National Copyright Administration of the
  People's Republic of China, and adopts the MIT license as the copyright
  licensing contract under which the right holder conditionally licenses its
  reproduction, distribution, and modification rights to an unspecified public.

    If you use Losu, please follow the public MIT agreement or choose to enter
  into a dedicated license agreement with us.

  The MIT LICENSE is as follows
  --------------------
  Copyright  2020 - now  chen-chaochen

    Permission is hereby granted, free of charge, to any person obtaining a
  copy of this software and associated documentation files (the “Software”), to
  deal in the Software without restriction, including without limitation the
  rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
  sell copies of the Software, and to permit persons to whom the Software is
  furnished to do so, subject to the following conditions:

    The above copyright notice and this permission notice shall be included in
  all copies or substantial portions of the Software.

    THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  SOFTWARE.
*/

/*
    This document is part of the Losu Community OSPP - 2024 subject results
  contributed by Dongqiao Huang @ NEUQ, following MIT LICENSE Contributed to
  the Losu Community.

  The MIT LICENSE is as follows
  --------------------
  Copyright 2024 Dongqiao Huang

    Permission is hereby granted, free of charge, to any person obtaining a
  copy of this software and associated documentation files (the “Software”), to
  deal in the Software without restriction, including without limitation the
  rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
  sell copies of the Software, and to permit persons to whom the Software is
  furnished to do so, subject to the following conditions:

    The above copyright notice and this permission notice shall be included in
  all copies or substantial portions of the Software.

    THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  SOFTWARE.
 */

#include "hCodegen.hh"

#include <iostream>

#include "hError.hh"

namespace LosuPreCompiler
{
using namespace Error;
namespace CodeGen
{

hCodegen::hCodegen (std::string fname)
{
  cgOutput *o = &this->output;
  // init the output
  // head file
  o->headFile.headcmt = "";
  o->headFile.declare = "";
  // source file
  o->srcFile.headcmt = "";
  o->srcFile.declare = "";
  o->srcFile.module = "";
  o->srcFile.submod = "";
  o->srcFile.classs = "";
  o->srcFile.object = "";
  o->srcFile.func = "";
  // markdown
  o->mdFile.headcmt = "";
  o->mdFile.menu = "";
  o->mdFile.text = "";

  this->fname = fname;
}

/**
 * @brief add a module to the codegen
 * @param module the module to add
 */
void
hCodegen::addModule (cgType_module module, std::int32_t line)
{
  this->mainModule = module;
  return;
}

/**
 * @brief add a submod to the codegen, at the root node
 * @param submod the submod to add
 * @param root the root node
 * @param line the line number
 */
void
hCodegen::addSubmod (cgType_submod submod, std::vector<cgType_submod> *root,
                     std::int32_t line)
{
  for (std::size_t i = 0; i < root->size (); i++)
    if (root->at (i).name == submod.name)
      throw hError_t (
          std::string ("submod name conflict: '" + submod.name + "'."), line,
          hError::errCode::eCode_Codegen);
  root->push_back (submod);
  return;
}

/**
 * @brief add a class to the codegen, at the root node
 * @param cls the class to add
 * @param root the root node
 * @param line the line number
 */
void
hCodegen::addClass (cgType_class cls, std::vector<cgType_class> *root,
                    std::int32_t line)
{
  for (std::size_t i = 0; i < root->size (); i++)
    if (root->at (i).name == cls.name)
      throw hError_t (std::string ("class name conflict: '" + cls.name + "'."),
                      line, hError::errCode::eCode_Codegen);
  root->push_back (cls);
  return;
}

/**
 * @brief add an object to the codegen, at the root node
 * @param obj the object to add
 * @param root the root node
 * @param line the line number
 */
void
hCodegen::addObject (cgType_object obj, std::vector<cgType_object> *root,
                     std::int32_t line)
{
  for (std::size_t i = 0; i < root->size (); i++)
    if (root->at (i).name == obj.name)
      throw hError_t (
          std::string ("object name conflict: '" + obj.name + "'."), line,
          hError::errCode::eCode_Codegen);
  root->push_back (obj);
  return;
}

/**
 * @brief add a function to the codegen, at the root node
 * @param func the function to add
 * @param root the root node
 * @param line the line number
 */
void
hCodegen::addFunc (cgType_func func, std::vector<cgType_func> *root,
                   std::int32_t line)
{
  for (std::size_t i = 0; i < root->size (); i++)
    if (root->at (i).name == func.name)
      throw hError_t (
          std::string ("function name conflict: '" + func.name + "'."), line,
          hError::errCode::eCode_Codegen);
  root->push_back (func);
  return;
}

/**
 * @brief add a script to the codegen, at the root node
 * @param script the script to add
 * @param root the root node
 * @param line the line number
 */
void
hCodegen::addScript (cgType_script script, std::vector<cgType_script> *root,
                     std::int32_t line)
{
  for (std::size_t i = 0; i < root->size (); i++)
    if (root->at (i).name == script.name)
      throw hError_t (
          std::string ("script name conflict: '" + script.name + "'."), line,
          hError::errCode::eCode_Codegen);
  root->push_back (script);
  return;
}

/**
 * @brief add a number to the codegen, at the root node
 * @param num the number to add
 * @param root the root node
 * @param line the line number
 */
void
hCodegen::addNumber (cgType_number num, std::vector<cgType_number> *root,
                     std::int32_t line)
{
  for (std::size_t i = 0; i < root->size (); i++)
    if (root->at (i).name == num.name)
      throw hError_t (
          std::string ("number name conflict: '" + num.name + "'."), line,
          hError::errCode::eCode_Codegen);
  root->push_back (num);
}

/**
 * @brief add a string to the codegen, at the root node
 * @param str the string to add
 * @param root the root node
 * @param line the line number
 */
void
hCodegen::addString (cgType_string str, std::vector<cgType_string> *root,
                     std::int32_t line)
{
  for (std::size_t i = 0; i < root->size (); i++)
    if (root->at (i).name == str.name)
      throw hError_t (
          std::string ("string name conflict: '" + str.name + "'."), line,
          hError::errCode::eCode_Codegen);
  root->push_back (str);
  return;
}

/**
 * @brief generate code
 */
cgOutput
hCodegen::genCode ()
{
  try
    {
      this->p_genModule (this->mainModule);
      return this->output;
    }
  catch (hError_t &err)
    {
      // hError ("Syntax-Codegen", this->fname, err.getLine (), err.getEcode
      // (),
      //         err.getErr ());
      std::cout << "P1" << std::endl;
      exit (1);
    }
}

/**
 * @brief generate code for a module
 * @param mod the module to generate code for
 */
void
hCodegen::p_genModule (cgType_module mod)
{
#define outC this->output.srcFile.module
#define outH this->output.headFile.declare

  // declare
  outH += "LosuModule *__losuh__LOADMODULE_" + mod.name + "();\n";
  // module list
  outC += mod.comment + "\n";
  outC += "static LosuModule __losuh__MODULELIST[] = {\n";
  for (std::size_t i = 0; i < mod.subMod.size (); i++)
    outC += "{\"" + mod.subMod[i].name + "\"," + "__losuh__submod_"
            + mod.subMod[i].name + "_" + mod.name + "},\n";
  outC += "{NULL,NULL},\n};\n";

  // module loader
  outC += "LosuModule *__losuh__LOADMODULE_" + mod.name
          + "() {\nreturn &__losuh__MODULELIST[0];\n}\n";

  // codgen member:
  //    submod
  for (std::size_t i = 0; i < mod.subMod.size (); i++)
    this->p_genSmod (mod.subMod[i], mod.name);

#undef outC
#undef outH
}

/**
 * @brief generate code for a sub-module
 * @param submod the sub-module to generate code for
 * @param pname the parent module name
 */
void // pname = mod.name
hCodegen::p_genSmod (cgType_submod submod, std::string pname)
{
#define outC this->output.srcFile.submod
#define outH this->output.srcFile.declare

  // declare submod
  outH += "static int32_t __losuh__submod_" + submod.name + "_" + pname
          + "(LosuVm *vm);\n";

  // submod loader
  //    comment
  outC += submod.comment + "\n";
  outC += "static int32_t __losuh__submod_" + submod.name + "_" + pname
          + "(LosuVm *vm) {\n";
  // codegen member
  //    number
  {
    outC += "// constructors of number in " + submod.name + "\n";
    for (std::size_t i = 0; i < submod.subNum.size (); i++)
      {
        outC += submod.subNum[i].comment + "\n";
        outC += "__losuhAPI_regNumber(vm,\"" + submod.subNum[i].name + "\","
                + submod.subNum[i].value + ");\n";
      }
    outC += "\n";
  }
  //    string
  {
    outC += "// constructors of string in " + submod.name + "\n";
    for (std::size_t i = 0; i < submod.subStr.size (); i++)
      {
        outC += submod.subStr[i].comment + "\n";
        outC += "__losuhAPI_regString(vm,\"" + submod.subStr[i].name + "\","
                + submod.subStr[i].value + ");\n";
      }
    outC += "\n";
  }
  //    function
  {
    outC += "// constructors of function in " + submod.name + "\n";
    for (std::size_t i = 0; i < submod.subFunc.size (); i++)
      {
        outC += submod.subFunc[i].comment + "\n";
        outC += "__losuhAPI_regFunc(vm,\"" + submod.subFunc[i].name + "\"," +
                /* inline func name */
                ("__losuh__func_" + submod.subFunc[i].name + "_" + submod.name
                 + "_" + pname)
                + ");\n";
      }
    outC += "\n";
  }
  //    script
  {
    outC += "// constructors of script in " + submod.name + "\n";
    for (std::size_t i = 0; i < submod.subScript.size (); i++)
      {
        std::string ilineName = "__losuh__script_" + submod.subScript[i].name
                                + "_" + submod.name + "_" + pname;
        outC += submod.subScript[i].comment + "\n";
        outC += "__losuhAPI_regScript(vm,\"" + submod.subScript[i].name + "\","
                + ilineName + ",sizeof(" + ilineName + "));\n";
      }
    outC += "\n";
  }
  //    object
  {
    outC += "// constructors of object in " + submod.name + "\n";
    for (std::size_t i = 0; i < submod.subObj.size (); i++)
      {
        outC += submod.subObj[i].comment + "\n";
        outC += "__losuhAPI_regObject(vm,\"" + submod.subObj[i].name + "\"," +
                /* inline object name */
                ("__losuh__obj_" + submod.subObj[i].name + "_" + submod.name
                 + "_" + pname)
                + "(vm));\n";
      }
    outC += "\n";
  }
  //    class
  {
    outC += "// constructors of class in " + submod.name + "\n";
    for (std::size_t i = 0; i < submod.subCls.size (); i++)
      {
        outC += submod.subCls[i].comment + "\n";
        outC += "__losuhAPI_regClass(vm,\"" + submod.subCls[i].name + "\"," +
                /* inline class name */
                ("__losuh__class_" + submod.subCls[i].name + "_" + submod.name
                 + "_" + pname)
                + "(vm));\n";
      }
    outC += "\n";
  }
  // tail
  {
    outC += "\nreturn 0;\n}\n";
  }
  // call member constructor
  {
    // object
    for (std::size_t i = 0; i < submod.subObj.size (); i++)
      this->p_genObject (submod.subObj[i], submod.name + "_" + pname);
    // class
    for (std::size_t i = 0; i < submod.subCls.size (); i++)
      this->p_genClass (submod.subCls[i], submod.name + "_" + pname);
    // script
    for (std::size_t i = 0; i < submod.subScript.size (); i++)
      this->p_genSpt (submod.subScript[i], submod.name + "_" + pname);
    // func
    for (std::size_t i = 0; i < submod.subFunc.size (); i++)
      this->p_genFunc (submod.subFunc[i], submod.name + "_" + pname);
  }

#undef outC
#undef outH
}

/**
 * @brief generate object
 * @param object object to generate code for
 * @param pname the parent name of the object
 */
void // pname = xxx_xxx
hCodegen::p_genObject (cgType_object object, std::string pname)
{
#define outC this->output.srcFile.object
#define outH this->output.srcFile.declare

  // declare
  outH += "static LosuObj __losuh__obj_" + object.name + "_" + pname
          + "(LosuVm *vm);\n";

  // constructor of object
  //    comment
  outC += object.comment + "\n";
  //    loader
  outC += "static LosuObj __losuh__obj_" + object.name + "_" + pname
          + "(LosuVm *vm){\nLosuObj newObj = obj_newunit(vm);\n";

  // bind member
  //    number
  {
    outC += "// constructor of number in " + object.name + "@" + pname + "\n";
    for (std::size_t i = 0; i < object.subNum.size (); i++)
      {
        cgType_number sNum = object.subNum[i];
        outC += sNum.comment + "\n";
        outC += "__losuhAPI_regObjNumber(vm,newObj,\"" + sNum.name + "\","
                + sNum.value + ");\n";
      }
    outC += "\n";
  }
  //    string
  {
    outC += "// constructor of string in " + object.name + "@" + pname + "\n";
    for (std::size_t i = 0; i < object.subStr.size (); i++)
      {
        cgType_string sStr = object.subStr[i];
        outC += sStr.comment + "\n";
        outC += "__losuhAPI_regObjString(vm,newObj,\"" + sStr.name + "\",\""
                + sStr.value + "\");\n";
      }
    outC += "\n";
  }
  //    object
  {
    outC += "// constructor of object in " + object.name + "@" + pname + "\n";
    for (std::size_t i = 0; i < object.subObj.size (); i++)
      {
        cgType_object sObj = object.subObj[i];
        outC += sObj.comment + "\n";
        outC += "__losuhAPI_regObjObject(vm,newObj,\"" + sObj.name + "\","
                + "__losuh__obj_" + sObj.name + "_" + object.name + "_" + pname
                + "(vm));\n";
      }
    outC += "\n";
  }
  //    class
  {
    outC += "// constructor of class in " + object.name + "@" + pname + "\n";
    for (std::size_t i = 0; i < object.subCls.size (); i++)
      {
        cgType_class sCls = object.subCls[i];
        outC += sCls.comment + "\n";
        outC += "__losuhAPI_regObjClass(vm,newObj,\"" + sCls.name + "\",\""
                + this->p_getPname (sCls.name, object.name, pname) + "\","
                + "__losuh__class_" + sCls.name + "_" + object.name + "_"
                + pname + "(vm));\n";
      }
    outC += "\n";
  }
  //    function
  {
    outC
        += "// constructor of function in " + object.name + "@" + pname + "\n";
    for (std::size_t i = 0; i < object.subFunc.size (); i++)
      {
        cgType_func sFun = object.subFunc[i];
        outC += sFun.comment + "\n";
        outC += "__losuhAPI_regObjFunc(vm,newObj,\"" + sFun.name
                + "\","
                /* Inline func name */
                + "__losuh__func_" + sFun.name + "_" + object.name + "_"
                + pname + ");\n";
      }
    outC += "\n";
  }
  // tail
  {
    outC += "return newObj;\n}\n";
  }
  // call member constructor
  {
    for (std::size_t i = 0; i < object.subObj.size (); i++)
      this->p_genObject (object.subObj[i], object.name + "_" + pname);
    for (std::size_t i = 0; i < object.subCls.size (); i++)
      this->p_genClass (object.subCls[i], object.name + "_" + pname);
    for (std::size_t i = 0; i < object.subFunc.size (); i++)
      this->p_genFunc (object.subFunc[i], object.name + "_" + pname);
  }

#undef outC
#undef outH
}

/**
 * @brief Generate Class
 * @param cls class to generate
 * @param pname parent name
 */
void // pname = xxx_xxx
hCodegen::p_genClass (cgType_class cls, std::string pname)
{
#define outC this->output.srcFile.classs
#define outH this->output.srcFile.declare

  // declare
  outH += "static LosuObj __losuh__class_" + cls.name + "_" + pname
          + "(LosuVm *vm);\n";

  // constructor of class
  //    comment
  outC += cls.comment + "\n";
  //    loader
  outC += "static LosuObj __losuh__class_" + cls.name + "_" + pname
          + "(LosuVm *vm){\nLosuObj newObj = obj_newunit(vm);\n";
  // codegen member
  //    number
  {
    outC += "// constructor of number in " + cls.name + "@" + pname + "\n";
    for (std::size_t i = 0; i < cls.subNum.size (); i++)
      {
        cgType_number sNum = cls.subNum[i];
        outC += sNum.comment + "\n";
        outC += "__losuhAPI_regObjNumber(vm,newObj,\"" + sNum.name + "\","
                + sNum.value + ");\n";
      }
    outC += "\n";
  }
  //    string
  {
    outC += "// constructor of string in " + cls.name + "@" + pname + "\n";
    for (std::size_t i = 0; i < cls.subStr.size (); i++)
      {
        cgType_string sStr = cls.subStr[i];
        outC += sStr.comment + "\n";
        outC += "__losuhAPI_regObjString(vm,newObj,\"" + sStr.name + "\",\""
                + sStr.value + "\");\n";
      }
    outC += "\n";
  }
  //    function
  {
    outC += "// constructor of function in " + cls.name + "@" + pname + "\n";
    for (std::size_t i = 0; i < cls.subFunc.size (); i++)
      {
        cgType_func sFun = cls.subFunc[i];
        outC += sFun.comment + "\n";
        outC += "__losuhAPI_regObjFunc(vm,newObj,\"" + sFun.name
                + "\","
                /* Inline func name */
                + "__losuh__func_" + sFun.name + "_" + cls.name + "_" + pname
                + ");\n";
      }
    outC += "\n";
  }
  // tail
  {
    outC += "return newObj;\n}\n";
  }
  // call member constructor
  {
    for (std::size_t i = 0; i < cls.subFunc.size (); i++)
      this->p_genFunc (cls.subFunc[i], cls.name + "_" + pname);
  }

#undef outC
#undef outH
}

/**
 * @brief Generate function
 * @param func function to generate
 * @param pname parent name
 */
void // pname = xxx_xxx
hCodegen::p_genFunc (cgType_func func, std::string pname)
{
#define outC this->output.srcFile.func
#define outH this->output.headFile.declare

  // declare
  outH += func.comment + "\n";
  outH += "int32_t __losuh__func_" + func.name + "_" + pname
          + "(LosuVm *vm);\n";
  // constructor of function
  //    comment
  // outC += func.comment + "\n";
  //    loader
  // outC += "int32_t __losuh__func_" + func.name + "_" + pname
  //         + "(LosuVm *vm){\nreturn 0;\n}\n";
  // outC += "int32_t __losuh__func_" + func.name + "_" + pname
  //         + "(LosuVm *vm);\n";
#undef outC
#undef outH
}

void // pname = xxx_xxx
hCodegen::p_genSpt (cgType_script spt, std::string pname)
{
#define outH this->output.srcFile.declare

  outH += "static const char __losuh__script_" + spt.name + "_" + pname
          + "[] = \n#include \"" + spt.file + ".inc\"\n;\n";
  outH += "\n";
#undef outH
}

std::string
hCodegen::p_getPname (std::string cls, std::string obj, std::string pname)
{
  std::string ret = "";
  std::vector<std::string> vec;
  ret += obj + "." + cls;
  // token pname
  const char *str = new char[pname.length () + 1];
  std::memcpy ((void *)str, pname.c_str (), pname.length () + 1);

  const char *token = std::strtok ((char *)str, "_");
  while (token != NULL)
    {
      vec.push_back (std::string (token));
      token = std::strtok (NULL, "_");
    }
  if (vec.size () > 2)
    {
      for (std::size_t i = 0; i < vec.size () - 2; i++)
        ret = vec[i] + "." + ret;
    }
  return ret;
}

} // namespace CodeGen
} // namespace LosuPreCompiler

// #define HCODEGENCC_MAIN
#ifdef HCODEGENCC_MAIN

#include <fstream>
#include <iostream>

using namespace LosuPreCompiler;
using namespace CodeGen;
using namespace Error;

int
main ()
{
  std::ofstream ofile;
  cgType_module mod_stdlib = {
    .name = "stdlib",
  };
  hCodegen cGen ("demo.els.c");

  try
    {
      cgType_submod smod_stdaux, smod_stdio, smod_stdfile;
      cgType_class cls_file;
      cgType_object obj_time, obj_date_time;
      cgType_number num_PI, num_year0;
      cgType_string str_version;
      cgType_func Fprint, Fclock, Fday, Fread;

      /**
       * module stdlib
       *    sub stdio
       *        def print()
       *    sub stdaux
       *        number PI 3.14
       *        string version "1.0"
       *        object time
       *            number year0 "1900"
       *            def clock()
       *            object data
       *                def day()
       *        script demo "demo.els"
       *    sub stdfile
       *        class file():
       *            read()
       */
      {
        smod_stdio = (cgType_submod){
          .name = "stdio",
        };
        smod_stdaux = (cgType_submod){
          .name = "stdaux",
        };
        smod_stdfile = (cgType_submod){
          .name = "stdfile",
        };
        cls_file = (cgType_class){
          .name = "file",
        };
        obj_time = (cgType_object){
          .name = "time",

        };
        obj_date_time = (cgType_object){
          .name = "date",
        };
        num_PI = (cgType_number){
          .name = "PI",
          .value = "3.14",
        };
        num_year0 = (cgType_number){
          .name = "year0",
          .value = "1900",
        };
        str_version = (cgType_string){
          .name = "version",
          .value = "1.0",
        };
        Fprint = (cgType_func){
          .name = "print",
        };
        Fclock = (cgType_func){
          .name = "clock",
        };
        Fday = (cgType_func){
          .name = "day",
        };
        Fread = (cgType_func){
          .name = "read",
        };
      }
      {
        cGen.addFunc (Fprint, &smod_stdio.subFunc, 1);
        cGen.addSubmod (smod_stdio, &mod_stdlib.subMod, 1);

        cGen.addFunc (Fday, &obj_date_time.subFunc, 1);
        cGen.addObject (obj_date_time, &obj_time.subObj, 1);
        cGen.addNumber (num_year0, &obj_time.subNum, 1);
        cGen.addFunc (Fclock, &obj_time.subFunc, 1);
        cGen.addObject (obj_time, &smod_stdaux.subObj, 1);
        cGen.addNumber (num_PI, &smod_stdaux.subNum, 1);
        cGen.addString (str_version, &smod_stdaux.subStr, 1);
        cGen.addScript (
            (cgType_script){
                .name = "demoInline",
                .file = "demoInline.inc",
            },
            &smod_stdaux.subScript, 1);
        cGen.addSubmod (smod_stdaux, &mod_stdlib.subMod, 1);

        cGen.addFunc (Fread, &cls_file.subFunc, 1);
        cGen.addClass (cls_file, &smod_stdfile.subCls, 1);
        cGen.addSubmod (smod_stdfile, &mod_stdlib.subMod, 1);

        cGen.addModule (mod_stdlib, 1);
      }
      {
        cgOutput out = cGen.genCode ();
        std::ofstream ofile ("test/demo.els.c");
        std::ofstream hfile ("test/demo.els.h");
        hfile << out.headFile.headcmt << std::endl
              << out.headFile.declare << std::endl;
        ofile << out.srcFile.headcmt << std::endl
              << out.srcFile.declare << std::endl
              << out.srcFile.module << std::endl
              << out.srcFile.submod << std::endl
              << out.srcFile.object << std::endl
              << out.srcFile.classs << std::endl
              << out.srcFile.func << std::endl;
        hfile.close ();
        ofile.close ();
      }
    }
  catch (hError_t &err)
    {
      hError ("Syntax-Codegen", "demo.els", err.getLine (), err.getEcode (),
              err.getErr ());
    }
}

#endif